// src/utils/request.ts
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from "axios";

// 定义后端返回的统一数据结构
interface ApiResponse<T = any> {
  code: number;
  data: T;
  message: string;
}

// 扩展AxiosRequestConfig类型，加入自定义配置
interface CustomRequestConfig extends AxiosRequestConfig {
  noAuth?: boolean; // 是否需要认证
  handleError?: boolean; // 是否自行处理错误
}

export class Request {
  private instance: AxiosInstance;
  private readonly baseConfig: CustomRequestConfig = {
    baseURL: import.meta.env.VITE_API_BASE_URL, // 从环境变量读取
    timeout: 10000,
    headers: { "Content-Type": "application/json" },
  };

  constructor(config?: CustomRequestConfig) {
    this.instance = axios.create(Object.assign(this.baseConfig, config));

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 添加认证token
        const token = localStorage.getItem("token");
        if (token && !(config as CustomRequestConfig).noAuth) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        // 直接返回后端数据（剥离外层包装）
        const res = response.data;

        // 根据业务状态码处理结果
        if (res.code === 0) {
          return res.data;
        }

        // 特殊状态码处理（如token过期）
        if (res.code === 401) {
          this.handleUnauthorized();
          return Promise.reject(res);
        }

        // 默认业务错误处理
        if (!(response.config as CustomRequestConfig).handleError) {
          this.handleBusinessError(res);
        }
        return Promise.reject(res);
      },
      (error: AxiosError) => {
        // HTTP状态码错误处理
        if (!(error.config as CustomRequestConfig)?.handleError) {
          this.handleHttpError(error);
        }
        return Promise.reject(error);
      }
    );
  }

  /**
   * 处理HTTP网络错误
   * @param error 错误对象
   */
  private handleHttpError(error: AxiosError) {
    let message = "";
    if (error.response) {
      switch (error.response.status) {
        case 400:
          message = "请求错误(400)";
          break;
        case 401:
          message = "未授权，请重新登录(401)";
          this.handleUnauthorized();
          break;
        case 403:
          message = "拒绝访问(403)";
          break;
        case 404:
          message = "资源不存在(404)";
          break;
        case 500:
          message = "服务器错误(500)";
          break;
        default:
          message = `连接出错(${error.response.status})!`;
      }
    } else {
      message = "网络连接异常，请检查网络!";
    }
    console.error("HTTP Error:", message);
    // 实际项目中可使用UI组件显示错误
    // message.error(message);
  }

  /**
   * 处理业务逻辑错误
   * @param res 后端响应
   */
  private handleBusinessError(res: ApiResponse) {
    const message = res.message || "未知业务错误";
    console.error("Business Error:", message, res.code);
    // 实际项目中可使用UI组件显示错误
    // message.error(message);
  }

  /**
   * 处理未授权情况
   */
  private handleUnauthorized() {
    console.error("认证过期，请重新登录");
    // 实际项目中执行登出操作
    localStorage.removeItem("token");
    window.location.href = "/login";
  }

  /**
   * 通用请求方法
   * @param config 请求配置
   */
  public request<T = any>(config: CustomRequestConfig): Promise<T> {
    return this.instance.request(config);
  }

  /**
   * GET请求
   * @param url 请求地址
   * @param params 查询参数
   * @param config 额外配置
   */
  public get<T = any>(url: string, params?: object, config?: CustomRequestConfig): Promise<T> {
    return this.request({ url, params, method: "GET", ...config });
  }

  /**
   * POST请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 额外配置
   */
  public post<T = any>(url: string, data?: object, config?: CustomRequestConfig): Promise<T> {
    return this.request({ url, data, method: "POST", ...config });
  }
}

// 创建请求实例
const request = new Request();
export default request;
